﻿using hmc.im.service.core;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace hmc.im.service
{
    class Program
    {
        private static byte[] result = new byte[1024];
        private static int serverProt = int.Parse(System.Configuration.ConfigurationManager.AppSettings["ServerPort"]);   //端口  
        private static string serverIP = System.Configuration.ConfigurationManager.AppSettings["ServerIP"];   //端口  
        static Socket serverSocket;

        static void Main(string[] args)
        {
            try
            {
                //服务器IP地址  
                IPAddress ip = IPAddress.Parse(serverIP);
                serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                serverSocket.Bind(new IPEndPoint(ip, serverProt));  //绑定IP地址：端口  
                serverSocket.Listen(100);    //设定最多10个排队连接请求  
                Logger.Writer("HMC.IM Service Start Sucess");
                Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString());

                //通过Clientsoket发送数据  
                Thread listenThread = new Thread(ListenClientConnect);
                listenThread.Start();


                //Console.ReadLine();
                for (; ; )
                    Thread.Sleep(10000);
            }
            catch (Exception ex)
            {
                Logger.Writer("HMC.IM Service Start Error[" + ex.Message + "]");
                Logger.Writer(ex);
                throw ex;
            }
            //Thread.Sleep(1000);
        }

        private static int ListenThreadCount = 0;



        /// <summary>  
        /// 监听客户端连接  
        /// </summary>  
        private static void ListenClientConnect()
        {
            ListenThreadCount++;

            Logger.Writer("ListenThread Start " + ListenThreadCount);
            //Console.WriteLine("ListenThread Start " + ListenThreadCount);
            int i = 0;
            while (true)
            {
                i++;
                Socket clientSocket = serverSocket.Accept();
                Logger.Writer("客户端[" + clientSocket.RemoteEndPoint.ToString() + "]发送登录请求" + i);
                //Console.WriteLine("客户端发送登录请求" + i);


                //通过clientSocket接收数据  
                int receiveNumber = clientSocket.Receive(result);
                if (receiveNumber > 0)
                {
                    string receiveresult = Encoding.ASCII.GetString(result, 0, receiveNumber);
                    CommandResultEntity commandResult = CommandBusiness.Execute(receiveresult, clientSocket.RemoteEndPoint.ToString());

                    if (commandResult.CommandType == EnumDirectiveType.Login)
                    {
                        //通知客户端登录情况
                        clientSocket.Send(Encoding.ASCII.GetBytes((int)commandResult.CommandType + "|" + commandResult.Status.ToString() + "," + commandResult.Message));
                        #region 登录成功之后立即发送订单提醒信息
                        if (commandResult.Status == true)
                        {
                            object[] param = new object[] { clientSocket, commandResult.UserAccessToken };
                            //登录成功之后立即启动发送消息
                            Thread sendThread = new Thread(SendMessage);
                            sendThread.Start(param);

                            //登录成功之后立即启动接收客户端信息
                            Thread receiveThread = new Thread(ReceiveMessage);
                            receiveThread.Start(clientSocket);

                        }
                        #endregion
                    }
                    else if (commandResult.CommandType == EnumDirectiveType.HandClasp)
                    {
                        clientSocket.Send(Encoding.ASCII.GetBytes((int)commandResult.CommandType + "|" + commandResult.Status.ToString() + "," + commandResult.Message));
                    }
                }
            }
        }



        /// <summary>
        /// 发送订单通知
        /// </summary>
        /// <param name="clientSocket"></param>
        private static void SendMessage(object param)
        {
            object[] values = param as object[];

            Socket myClientSocket = (Socket)values[0];
            UserAccessTokenEntity userEntity = (UserAccessTokenEntity)values[1];



            DateTime start = DateTime.Parse("2013-09-16 00:53:00");
            long startTime = 0;
            if (userEntity.LastExitTime > 0) startTime = userEntity.LastExitTime;
            else startTime = userEntity.LastLoginTime;

            int i = 0;
            //DateTime end = DateTime.Now;
            while (true)
            {
                i++;

                #region 客户端不在线则退出
                if (myClientSocket == null || myClientSocket.Connected == false)
                {
                    //Console.WriteLine("Receive:客户端已关闭");
                    break;
                }
                #endregion

                //判断客户端是否在线
                if (userEntity.LastCcommunication.AddMinutes(int.Parse(ConfigurationManager.AppSettings["TimeOut"])) < DateTime.Now)
                {
                    string clientEndPoint = myClientSocket.RemoteEndPoint.ToString();
                    //客户端超时
                    myClientSocket.Close();
                    Logger.Writer("SEND:超时,关闭连接,客户端[" + userEntity.UserName + "," + clientEndPoint + "]");
                    //Console.WriteLine("SEND:客户端[" + userEntity.UserName + "," + clientEndPoint + "]连接关闭");
                    UserAccessTokenDB.DB.Remove(userEntity);

                    //var q = (from p in UserAccessTokenDB.DB where p.UserName == userEntity.UserName select p).SingleOrDefault();
                    //if (q == null) Console.WriteLine("SEND：从在线列表中移除");
                    //else Console.WriteLine("SEND：没有从在线列表中移除");
                    //Console.WriteLine("SEND：客户端已关闭");

                    break;
                }

                //Console.WriteLine("SEND:客户端[" + userEntity.UserName + "," + myClientSocket.RemoteEndPoint.ToString() + "]连接状态：" + myClientSocket.Connected + ",最后通讯时间" + userEntity.LastCcommunication.ToString());

                try
                {
                    core.OrderNotify ordern = new core.OrderNotify();
                    int count = ordern.GetNewOrderCount(startTime, out startTime);

                    if (count > 0)
                    {
                        myClientSocket.Send(Encoding.ASCII.GetBytes((int)EnumDirectiveType.Hint + "|true," + count));
                        Logger.Writer("向客户端[" + userEntity.UserName + "," + myClientSocket.RemoteEndPoint.ToString() + "]发送消息" + i);
                    }

                }
                catch (Exception ex)
                {
                    Logger.Writer(ex);
                    //Console.WriteLine(ex.Message);
                    myClientSocket.Shutdown(SocketShutdown.Both);
                    myClientSocket.Close();
                    break;
                }

                Thread.Sleep(60000);

            }
        }

        /// <summary>  
        /// 接收消息  
        /// </summary>  
        /// <param name="clientSocket"></param>  
        private static void ReceiveMessage(object clientSocket)
        {
            Socket myClientSocket = (Socket)clientSocket;
            while (true)
            {
                //Console.WriteLine("Receive:接收客户端[" + myClientSocket.RemoteEndPoint.ToString() + "]开始接收消息");
                if (myClientSocket == null || myClientSocket.Connected == false)
                {
                    //Console.WriteLine("Receive:客户端[" + myClientSocket.RemoteEndPoint.ToString() + "]已关闭");
                    break;
                }
                try
                {
                    //通过clientSocket接收数据  
                    int receiveNumber = myClientSocket.Receive(result);
                    if (receiveNumber > 0)
                    {
                        string receiveresult = Encoding.ASCII.GetString(result, 0, receiveNumber);
                        //Console.WriteLine("接收客户端[{0}]消息:{1}", myClientSocket.RemoteEndPoint.ToString(), receiveresult);

                        CommandResultEntity commandResult = CommandBusiness.Execute(receiveresult, myClientSocket.RemoteEndPoint.ToString());
                        if (commandResult.CommandType == EnumDirectiveType.HandClasp)
                        {
                            if (commandResult.Status == true) commandResult.UserAccessToken.LastCcommunication = DateTime.Now;//握手成功，更新列表中用户信息

                            //发送信息给客户端
                            myClientSocket.Send(Encoding.ASCII.GetBytes((int)commandResult.CommandType + "|" + commandResult.Status.ToString() + "," + commandResult.Message));
                        }
                        else if (commandResult.CommandType == EnumDirectiveType.Logout)
                        {
                            UserAccessTokenDB.DB.Remove(commandResult.UserAccessToken);
                            //Console.WriteLine("Receive:客户端[{0}]主动退出", myClientSocket.RemoteEndPoint.ToString());
                            Logger.Writer("Receive:客户端[" + myClientSocket.RemoteEndPoint.ToString() + "]主动退出");

                            //var q = (from p in UserAccessTokenDB.DB where p.UserName == commandResult.UserAccessToken.UserName select p).SingleOrDefault();
                            //if (q == null) Console.WriteLine("Receive:已经从在线列表中移除");
                            //else Console.WriteLine("Receive:没有从在线列表中移除");
                            //退出
                            myClientSocket.Close();
                            break;
                        }


                    }

                }
                catch (Exception ex)
                {
                    Logger.Writer(ex);
                    //Console.WriteLine(myClientSocket.RemoteEndPoint.ToString() + ex.Message);
                    //myClientSocket.Shutdown(SocketShutdown.Both);
                    //myClientSocket.Close();
                    break;
                }
            }
        }
    }
}
